<?php

declare(strict_types=1);

namespace app\service\factory;

use app\service\dto\ResultInterface;

class ResponseFactory
{
    /**
     * 创建统一的API响应格式
     * @param mixed $data 响应数据
     * @param string $message 响应消息
     * @param int $code 状态码
     * @param bool $success 是否成功
     * @return array
     */
    public static function createApiResponse($data = null, string $message = 'success', int $code = 200, bool $success = true): array
    {
        // 如果$data是ResultInterface实例，特殊处理
        if ($data instanceof ResultInterface) {
            return self::createFromResult($data);
        }

        return [
            'code' => $code,
            'msg' => $message,
            'data' => self::serialiseData($data),
            'success' => $success
        ];
    }

    /**
     * 创建成功响应
     * @param mixed $data 响应数据
     * @param string $message 响应消息
     * @param int $code 状态码
     * @return array
     */
    public static function success($data = null, string $message = 'success', int $code = 200): array
    {
        return self::createApiResponse($data, $message, $code, true);
    }

    /**
     * 创建错误响应
     * @param string $message 错误消息
     * @param mixed $data 响应数据
     * @param int $code 错误码
     * @return array
     */
    public static function error(string $message = 'error', int $code = 400, $data = null): array
    {
        return self::createApiResponse($data, $message, $code, false);
    }

    /**
     * 从结果对象创建响应
     * @param ResultInterface $result
     * @return array
     */
    public static function createFromResult(ResultInterface $result): array
    {
        return [
            'code' => $result->getCode(),
            'msg' => $result->getMessage(),
            'data' => self::serialiseData($result->getData()),
            'success' => $result->isSuccess()
        ];
    }

    /**
     * 创建分页响应
     * @param array $data 数据列表
     * @param int $total 总数
     * @param int $page 当前页
     * @param int $pageSize 每页数量
     * @param string $message 消息
     * @return array
     */
    public static function paginated(
        array $data,
        int $total,
        int $page,
        int $pageSize,
        string $message = 'success',
        array $extra = []
    ): array
    {
        $safePage = $page > 0 ? $page : 1;
        $safePageSize = $pageSize > 0 ? $pageSize : 1;
        $totalPage = (int) max(1, ceil($total / $safePageSize));

        $payload = array_merge([
            'list' => $data,
            'pagination' => [
                'total' => $total,
                'page' => $safePage,
                'currentPage' => $safePage,
                'pageSize' => $safePageSize,
                'totalPage' => $totalPage,
            ],
        ], $extra);

        return [
            'code' => 200,
            'msg' => $message,
            'data' => self::serialiseData($payload),
            'success' => true
        ];
    }

    private static function serialiseData($data)
    {
        if (is_object($data)) {
            if (method_exists($data, 'toArray')) {
                return $data->toArray();
            }

            if ($data instanceof \JsonSerializable) {
                return $data->jsonSerialize();
            }
        }

        return $data;
    }
}
